/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved.
 */

package com.huawei.housekeeper.exception;

import com.huawei.housekeeper.enums.ErrorCode;
import com.huawei.housekeeper.result.Result;
import com.huawei.saashousekeeper.exception.RoutingException;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.log4j.Log4j2;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Objects;

/**
 * 全局异常处理
 *
 * @author y00464350
 * @since 2022-02-11
 */
@Log4j2
@ControllerAdvice
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionHandler {

    @ExceptionHandler({ErrorCodeException.class})
    @ResponseBody
    public Result handleErrorCodeException(ErrorCodeException e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(e.getErrorCode(), e.getMessage());
    }

    @ExceptionHandler({ParameterNotValidException.class})
    @ResponseBody
    public Result handleErrorCodeException(ParameterNotValidException e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(e.getErrorCode(), e.getMessage());
    }

    @ExceptionHandler({RoutingException.class})
    @ResponseBody
    public Result handleErrorCodeException(RoutingException e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(ErrorCode.TENANT_ROUTING_ERROR.getCode(), ErrorCode.TENANT_ROUTING_ERROR.getMessage());
    }

    @ExceptionHandler({ExpiredJwtException.class})
    @ResponseBody
    public Result handleErrorCodeException(ExpiredJwtException e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(ErrorCode.TOKEN_EXPIRED.getCode(), ErrorCode.TOKEN_EXPIRED.getMessage());
    }

    @ExceptionHandler({ArgumentException.class})
    @ResponseBody
    public Result handleErrorCodeException(ArgumentException e) {
        log.warn(e.getLocalizedMessage(), e);
        return Result.createResult(e.getCode(), e.getMessage());
    }

    @ExceptionHandler({Exception.class})
    @ResponseBody
    public Result handleException(Exception e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(ErrorCode.UNKNOWN.getCode(), ErrorCode.UNKNOWN.getMessage());
    }

    @ExceptionHandler({MethodArgumentNotValidException.class})
    @ResponseBody
    public Result handleException(MethodArgumentNotValidException e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(Objects.requireNonNull(e.getFieldError()).getDefaultMessage());
    }

    @ExceptionHandler({AuthenticationException.class})
    @ResponseBody
    public Result handleException(AuthenticationException e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(ErrorCode.USERNAME_OR_PASSWORD_ERROR.getCode(), ErrorCode.USERNAME_OR_PASSWORD_ERROR.getMessage());
    }

    @ExceptionHandler({AccessDeniedException.class})
    @ResponseBody
    public Result handleException(AccessDeniedException e) {
        log.error(e.getLocalizedMessage(), e);
        return Result.createResult(ErrorCode.FORBIDDEN.getCode(), ErrorCode.FORBIDDEN.getMessage());
    }

}
